﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using FinPlusCommon;
using log = Logger.Logger;
using u = FinPlusUtility.Utility;

namespace FinPlusWPFControls
{
    public partial class FinPlusFilterbarTray : FinPlusControl
    {
        public override string Id { get; set; }
        public override string[] States { get { return new string[] { "Height", "Width", "Left", "Top" }; } }
        public override string[] TestStates { get { return new string[] { "ModelTest", "IsValid" }; } }
        public override IFinPlusFunctions Model { get { return base.Children(stackPanel.Children); } }
        public override string ModelTest { get { return Model.ToString(); } }
        public override bool IsValid { get; set; }

        public int ChildrenCount { get { return stackPanel.Children.Count; } }
        public string Filterbars
        {
            get { return string.Join(",", _filterOut.Select(x => x.Key).ToArray()); }
            set { foreach (var filterbar in value.Split(',')) AddFilterbar(new FinPlusFilterbar(filterbar)); }
        }
        public string FilteredOut
        {
            get { return string.Join(";", _filterOut.Select(x => x.Key + ":" + x.Value.FilteredOut).ToArray()); }
            set { foreach (var filterbar in value.Split(';')) { var x = filterbar.Split(':'); _filterOut[x[0]].FilteredOut = x[1]; } }
        }
        public ConcurrentDictionary<string, FinPlusFilterbar> FilterOut { get { return _filterOut; } }
        public event EventHandler<IFinPlusFunction> FilterUpdate;
        
        private enum DockControls { FinPlusFilterbar, FinPlusParentService, Exception, Default }
        
        private ConcurrentDictionary<string, FinPlusFilterbar> _filterOut = new ConcurrentDictionary<string, FinPlusFilterbar>();
        private FuncDynamics _funcsDynamic = null;

        //construct
        public FinPlusFilterbarTray()
        {
           InitializeComponent();
           IsValid = true;
        }

        //common control interface
        public override void Dock(object control, string dock)
        {
            try
            {
                switch(u.EnumTryParse<DockControls>(control.GetType().Name, DockControls.Default))
                {
                    case DockControls.FinPlusFilterbar: AddFilterbar((FinPlusFilterbar)control); break;
                    case DockControls.FinPlusParentService: AddConnection(((FinPlusParentService)control).GetFuncsTransposed()); break;
                    case DockControls.Exception: stackPanel.Children.Add(new FinPlusErrorDisplay((Exception)control)); break;
                    case DockControls.Default: stackPanel.Children.Add((UserControl)control); break;
                }
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Warning, e.Message, e);
                stackPanel.Children.Add(new FinPlusErrorDisplay(e));
            }
        }

        public override void Initialise()
        {

        }

        public override void CommandRouter(IFinPlusFunction func)
        {
            try
            {
                CaptureCommand(func);

                switch ((Commands)Enum.Parse(typeof(Commands), func.Name, true))
                {
                    case Commands.Refresh: Refresh(func); break;
                    default: throw new Exception(string.Format("event not recognised {0}", func.Name));
                }
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Warning, e.Message, e);
            }
        }

        public override void Dispose(){ }

        //public 
        public bool HasFilterbar(string name)
        {
            return _filterOut.ContainsKey(name);
        }

        public void AddConnection(FuncDynamics _conn)
        {
            try
            {
                _funcsDynamic = _conn;
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
                stackPanel.Children.Add(new FinPlusErrorDisplay(e));
            }
        }

        public void AddFilterbar(FinPlusFilterbar filterbar)
        {
            try
            {
                RemoveFilterbar(filterbar.Name);
                _filterOut[filterbar.Name] = filterbar;
                filterbar.AddViewSource(_funcsDynamic, Filter_Callback);
                stackPanel.Children.Add(filterbar);
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
                stackPanel.Children.Add(new FinPlusErrorDisplay(e));
            }
        }

        public void RemoveFilterbar(string name)
        {
            try
            {
                FinPlusFilterbar f = null;
                if (_filterOut.ContainsKey(name) && _filterOut.TryRemove(name, out f))
                {
                    stackPanel.Children.Remove(f);
                    Filter_Callback();
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
                stackPanel.Children.Add(new FinPlusErrorDisplay(e));
            }
        }

        //private
        private int Count()
        {
            return _funcsDynamic.Count();
        }

        private bool Refresh(IFinPlusFunction func)
        {
            FilterUpdate.Invoke(this, (Function)func);
            return true;
        }

        //cmds
        private new enum Commands { Refresh }

        //events
        private void Filter_Callback() { CommandRouter(new Function(Commands.Refresh.ToString(), Id, User)); }
    }
}
